﻿/////////////////////////////////////////////////////////////////////
//
//	Map_FVG C# Class Library.
//
//	Print2a
//	
//
//	autore: Gustavo Mainardi 
//	versione: 1.0
//	data: 01/12/2015
//
//
//	Cronologia delle versioni:
//
//	Versione 1.0 01/12/2015
//		versione originale
//
//////////////////////////////////////////////////////////////////////////
using System;
using System.Drawing;

namespace Map_Fvg
{
    public partial class Print 
    {
        public void arenile1(PdfFileWriter.PdfContents Contents, int nVertices, double dash0, double dash1, double dist_linee, double offset, int ist, int lst)
        {

            char[] delimiterChars0 = { ',', '/' };
            string[] words;
  
            int nParts = ViewQ.vectShapesA[ist].nParts;

            int[] ipart = new int[nParts + 1];
            if (nParts > 1)
            {
                string sp = ViewQ.vectShapesA[ist].Parts_string;
                words = sp.Split(delimiterChars0);
                for (int j = 0; j < nParts; ++j) ipart[j] = int.Parse(words[j]);
            }
            else ipart[0] = 0;
            ipart[nParts] = nVertices;

            int[] lpart = new int[nParts + 1];
            areaInt[] vect = new areaInt[nParts + 1];

            int nPoints = 0;
            PointF[] polyD = new PointF[1];
            PointF[] poly1 = new PointF[1];
            PointF[] poly = new PointF[1];

            double scala = 1.0 / double.Parse(this.textBox1.Text);
            double Xdiff = 1000 * (ViewQ.Xmax - ViewQ.Xmin) * scala;
            double Ydiff = 1000 * (ViewQ.Ymax - ViewQ.Ymin) * scala;

            double YYtrasl = 1000.0 * (ViewQ.vert[0].Y - ViewQ.vert[3].Y) * scala;

            double alphaR = ViewQ.alpha * Math.PI / 180.0D;
            double sinA = Math.Sin(alphaR);
            double cosA = Math.Cos(alphaR);
            double Ydiff1 = Ydiff - YYtrasl;

            double RGyy1 = height1 * Ydiff1 / DispHeight;
            double initXX = initX;
            double initYY = RGyy1 - initY - height1;
            double XX = initXX * cosA - initYY * sinA;
            double YY = initXX * sinA + initYY * cosA;
            double Xoff = Orig_X - (initXX / RGxx) * Xdiff;
            double Yoff = Orig_Y - (initYY / RGyy1) * Ydiff1;

            float xMin = 0;
            float xMax = 0;
            float yMin = 0;
            float yMax = 0;

            //
            //      per ogni area interna definire i puntatori, i vettori con coordinate locali e rettangoli d'ingombro
            //
            //      fissare dei valori per lo schermo e la stampa
            float interp = 2;
            if (lst == 1) interp = 0.5F;
            //      nel loop seguente si considera il bordo esterno
            for (int k = 0; k < 1; ++k)
            {
                int ipnt = ViewQ.vectShapesA[ist].pntPA + ipart[k];
                int iVertices = ipart[k + 1] - ipart[k];

                polyD = new PointF[iVertices];
                for (int j = 0; j < iVertices; ++j)
                {

                    double XX1 = 1000.0 * (ViewQ.PA[ipnt].X - ViewQ.Xmin) * scala;
                    double YY1 = 1000.0 * (ViewQ.PA[ipnt].Y - ViewQ.Ymin) * scala - YYtrasl;
                    polyD[j].X = (float)(XX1 * cosA + YY1 * sinA) + (float)Xoff;
                    polyD[j].Y = (float)(-XX1 * sinA + YY1 * cosA) + (float)Yoff;
                    ++ipnt;
                }

                normalize(polyD, ref poly1, interp, ist);

                nPoints = poly1.Length;
                poly = new PointF[nPoints];

                ipnt = ipart[k];
                vect[k].ipnt = ipnt;
                vect[k].nPoints = nPoints;

                for (int i = 0; i < nPoints; ++i) poly[i + ipnt] = poly1[i];

                xMin = poly[ipnt].X;
                xMax = poly[ipnt].X;
                yMin = poly[ipnt].Y;
                yMax = poly[ipnt].Y;

                for (int i = 1; i < nPoints; ++i)
                {
                    int ii = i + ipnt;
                    if (poly[ii].X < xMin) xMin = poly[ii].X;
                    if (poly[ii].X > xMax) xMax = poly[ii].X;
                    if (poly[ii].Y < yMin) yMin = poly[ii].Y;
                    if (poly[ii].Y > yMax) yMax = poly[ii].Y;
                }
                vect[k].Xmin = xMin;
                vect[k].Xmax = xMax;
                vect[k].Ymin = yMin;
                vect[k].Ymax = yMax;
            }


            PointF[] poly11 = new PointF[1];
            PointF[] polyZ = new PointF[nVertices];

            int nPoints1 = 0;

            if (nParts == 1) goto L100;

            int mpnt = 0;

            //      nel loop seguente si considerano i bordi interni
            for (int k = 1; k < nParts; ++k)
            {
                int ipnt = ViewQ.vectShapesA[ist].pntPA + ipart[k];
                int iVertices = ipart[k + 1] - ipart[k];
                polyD = new PointF[iVertices];
                for (int j = 0; j < iVertices; ++j)
                {
                    double XX1 = 1000.0 * (ViewQ.PA[ipnt].X - ViewQ.Xmin) * scala;
                    double YY1 = 1000.0 * (ViewQ.PA[ipnt].Y - ViewQ.Ymin) * scala - YYtrasl;
                    polyD[j].X = (float)(XX1 * cosA + YY1 * sinA) + (float)Xoff;
                    polyD[j].Y = (float)(-XX1 * sinA + YY1 * cosA) + (float)Yoff;
                    ++ipnt;
                }

                normalize(polyD, ref poly1, interp, ist);

                nPoints = poly1.Length;

                vect[k].ipnt = mpnt;
                vect[k].nPoints = nPoints;

                for (int i = 0; i < nPoints; ++i) polyZ[i + mpnt] = poly1[i];

                xMin = polyZ[mpnt].X;
                xMax = polyZ[mpnt].X;
                yMin = polyZ[mpnt].Y;
                yMax = polyZ[mpnt].Y;

                for (int i = 1; i < nPoints; ++i)
                {
                    int ii = i + mpnt;
                    if (polyZ[ii].X < xMin) xMin = polyZ[ii].X;
                    if (polyZ[ii].X > xMax) xMax = polyZ[ii].X;
                    if (polyZ[ii].Y < yMin) yMin = polyZ[ii].Y;
                    if (polyZ[ii].Y > yMax) yMax = polyZ[ii].Y;
                }
                vect[k].Xmin = xMin;
                vect[k].Xmax = xMax;
                vect[k].Ymin = yMin;
                vect[k].Ymax = yMax;

                mpnt += nPoints;
            }
            vect[nParts].ipnt = mpnt;

        L100:
            float x1 = 0;
            float x2 = 0;
            float y2 = 0;
            float Xpos0 = 0;
            float[] Xpos = new float[20];
            float[] XXpos = new float[20];
            int[] ipos = new int[20];
            int irept = 0;
            int jj = 0;
            float yPos = vect[0].Ymin;
            float XXoffset = 0;

            int inumMax = 10 * nParts;
            float[] Xpos1 = new float[inumMax];
            float[] XXpos1 = new float[inumMax];
            int[] ipos1 = new int[inumMax];


        L10: yPos += (float)dist_linee;
            XXoffset += (float)offset;
            if (yPos >= vect[0].Ymax) return;
            //
            //      irept = numero di intersezioni della retta orizzontale yPos con il bordo esterno
            //
            irept = 0;
            nPoints = vect[0].nPoints;

            for (int ii = 0; ii < nPoints - 1; ++ii)
            {
                if (poly[ii].Y > poly[ii + 1].Y)
                    if (yPos >= poly[ii + 1].Y && yPos < poly[ii].Y) ++irept;
                if (poly[ii].Y < poly[ii + 1].Y)
                    if (yPos < poly[ii + 1].Y && yPos >= poly[ii].Y) ++irept;
            }
            int irept2 = irept / 2;
            if (2 * irept2 < irept) goto L10;   //  le intersezioni dovrebbero essere di numero pari
            if (irept > 18) goto L10;
            ++jj;

            int inum = 0;

            // calcolo intersezioni retta orizzontale con bordo esterno 
            inum = 0;
            for (int ii = 0; ii < nPoints - 1; ++ii)
            {
                if (poly[ii].Y < 0) continue;
                if (poly[ii].Y > poly[ii + 1].Y)
                {
                    if (yPos >= poly[ii + 1].Y && yPos < poly[ii].Y)
                    {
                        x1 = poly[ii].X;
                        x2 = poly[ii + 1].X;
                        y2 = poly[ii + 1].Y;
                        Xpos0 = (yPos - y2) * (x1 - x2) / (poly[ii].Y - y2) + x2;
                        Xpos[inum] = Xpos0;
                        ++inum;
                    }
                    continue;
                }
                if (poly[ii].Y < poly[ii + 1].Y)
                    if (yPos < poly[ii + 1].Y && yPos >= poly[ii].Y)
                    {
                        x1 = poly[ii].X;
                        x2 = poly[ii + 1].X;
                        y2 = poly[ii + 1].Y;
                        Xpos0 = (yPos - y2) * (x1 - x2) / (poly[ii].Y - y2) + x2;
                        Xpos[inum] = Xpos0;
                        ++inum;
                    }
                if (inum >= 18) break;
            }
            //
            //      riordino vettore Xpos secondo valori crescenti
            //
            for (int i = 0; i < inum; ++i) ipos[i] = 0;
            for (int j = 0; j < inum; ++j)
            {
                int k = 0;
                for (k = 0; k < inum; ++k)
                {
                    if (ipos[k] == 0)
                    {
                        xMin = Xpos[k];
                        break;
                    }
                }

                int iptx = 0;
                for (int i = 0; i < inum; ++i)
                {
                    float fXP = Xpos[i];
                    if (i != k)
                    {
                        if (xMin > Xpos[i] && ipos[i] == 0)
                        {
                            xMin = Xpos[i];
                            iptx = i;
                        }
                    }
                    if (i == k) iptx = i;
                }
                XXpos[j] = Xpos[iptx];
                ipos[iptx] = 1;
            }

            int imax = (inum + 1) / 2;
            if (imax == 0) goto L10;
            float x5 = 0;
            float x6 = 0;
            float dashT = (float)(dash0 + dash1);

            for (int i = 0; i < imax; ++i)
            {
                int j = 2 * i;

                x5 = XXpos[j];
                if (XXoffset < x5)
                {
                    for (int k = 0; k < 1000; ++k) if (XXoffset + k * dashT >= x5)
                        {
                            x5 = XXoffset + k * dashT;
                            break;
                        }
                }
                if (XXoffset > x5)
                {
                    for (int k = 0; k < 1000; ++k) if (XXoffset - k * dashT <= x5)
                        {
                            x5 = XXoffset - (k - 1) * dashT;
                            break;
                        }
                }
                xMax = XXpos[j + 1];
                if (x5 > xMax) continue;

                //
                //          calcolo intersezioni con curva interna
                //
                if (nParts == 1) goto L30;

                inum = 0;
                for (int ik = 1; ik < nParts; ++ik)
                {
                    if (vect[ik].Ymin > yPos) continue;
                    if (vect[ik].Ymax < yPos) continue;
                    if (x5 > vect[ik].Xmax) continue;
                    if (xMax < vect[ik].Xmin) continue;
                    nPoints1 = vect[ik + 1].ipnt - vect[ik].ipnt;

                    mpnt = vect[ik].ipnt;
                    poly11 = new PointF[nPoints1];
                    for (int ii = 0; ii < nPoints1; ++ii) poly11[ii] = polyZ[ii + mpnt];

                    irept = 0;
                    for (int ii = 0; ii < nPoints1 - 1; ++ii)
                    {
                        if (poly11[ii].Y > poly11[ii + 1].Y)
                            if (yPos >= poly11[ii + 1].Y && yPos < poly11[ii].Y) ++irept;
                        if (poly11[ii].Y < poly11[ii + 1].Y)
                            if (yPos < poly11[ii + 1].Y && yPos >= poly11[ii].Y) ++irept;
                    }

                    if (irept == 0) continue;

                    float xx1 = 0;
                    float xx2 = 0;
                    float yy2 = 0;

                    for (int ii = 0; ii < nPoints1 - 1; ++ii)
                    {
                        if (poly11[ii].Y < 4.0) continue;
                        if (poly11[ii].Y > poly11[ii + 1].Y)
                        {
                            if (yPos >= poly11[ii + 1].Y && yPos < poly11[ii].Y)
                            {
                                xx1 = poly11[ii].X;
                                xx2 = poly11[ii + 1].X;
                                yy2 = poly11[ii + 1].Y;
                                Xpos0 = (yPos - yy2) * (xx1 - xx2) / (poly11[ii].Y - yy2) + xx2;
                                Xpos1[inum] = Xpos0;
                                ++inum;
                            }
                            continue;
                        }
                        if (poly11[ii].Y < poly11[ii + 1].Y)
                            if (yPos < poly11[ii + 1].Y && yPos >= poly11[ii].Y)
                            {
                                xx1 = poly11[ii].X;
                                xx2 = poly11[ii + 1].X;
                                yy2 = poly11[ii + 1].Y;
                                Xpos0 = (yPos - yy2) * (xx1 - xx2) / (poly11[ii].Y - yy2) + xx2;
                                Xpos1[inum] = Xpos0;
                                ++inum;
                            }
                        if (inum >= inumMax) break;
                    }
                }

                //
                //      riordino vettore Xpos1 secondo valori crescenti
                //
                if (inum == 0) goto L30;
                for (int ik = 0; ik < inum; ++ik) ipos1[ik] = 0;
                for (int jk = 0; jk < inum; ++jk)
                {
                    int k = 0;
                    for (k = 0; k < inum; ++k)
                    {
                        if (ipos1[k] == 0)
                        {
                            xMin = Xpos1[k];
                            break;
                        }
                    }

                    int iptx = 0;
                    for (int ik = 0; ik < inum; ++ik)
                    {
                        float fXP = Xpos1[ik];
                        if (ik != k)
                        {
                            if (xMin > Xpos1[ik] && ipos1[ik] == 0)
                            {
                                xMin = Xpos1[ik];
                                iptx = ik;
                            }
                        }
                        if (ik == k) iptx = ik;
                    }
                    XXpos1[jk] = Xpos1[iptx];
                    ipos1[iptx] = 1;
                }

                double X1 = 0;
                double Y1 = 0;
                double X2 = 0;
                double Y2 = 0;

                int inum2 = inum / 2;
                int ip = 0;
                for (int ik = 0; ik < inum2; ++ik)
                {
                    float xMax1;
                    xMax1 = XXpos1[ip];
                L20: x6 = x5 + (float)dash0;
                    if (x6 > xMax1) x6 = xMax1;

                   X1 = x5;
                    Y1 = yPos;
                    X2 = x6;
                    Y2 = yPos;
                    if (X1 >= 4.0 ) Contents.DrawLine(X1, Y1, X2, Y2);
 
                    x5 = x6 + (float)dash1;
                    if (x5 < xMax1) goto L20;

                    x5 = XXpos1[ip + 1];

                    if (XXoffset < x5)
                    {
                        for (int k = 0; k < 1000; ++k) if (XXoffset + k * dashT >= x5)
                            {
                                x5 = XXoffset + k * dashT;
                                break;
                            }
                    }
                    else if (XXoffset > x5)
                    {
                        for (int k = 0; k < 1000; ++k) if (XXoffset - k * dashT <= x5)
                            {
                                x5 = XXoffset - k * dashT;
                                break;
                            }
                    }
                    ip += 2;
                }

            L25: x6 = x5 + (float)dash0;
                if (x6 > xMax) x6 = xMax;

                X1 = x5;
                Y1 = yPos;
                X2 = x6;
                Y2 = yPos;
                if (X1 >= 4.0 ) Contents.DrawLine(X1, Y1, X2, Y2);

                x5 = x6 + (float)dash1;
                if (x5 < xMax) goto L25;
                continue;

            L30: x6 = x5 + (float)dash0;
                if (x6 > xMax) x6 = xMax;

                X1 = x5;
                Y1 = yPos;
                X2 = x6;
                Y2 = yPos;
                if (X1 >= 4.0 ) Contents.DrawLine(X1, Y1, X2, Y2);

                x5 = x6 + (float)dash1;
                if (x5 < xMax) goto L30;
            }

            goto L10;

        }
        void normalize(PointF[] polygon, ref PointF[] poly, float interp, int ist)
        {
            int nPoint = polygon.Length;
            PointF[] poly1 = new PointF[nPoint];
            poly1[0] = polygon[0];
            int ipt = 1;
            double dinterp = (double)interp;
            for (int i = 1; i < nPoint; ++i)
            {
                double dx = polygon[i].X - poly1[ipt - 1].X;
                double dy = polygon[i].Y - poly1[ipt - 1].Y;
                double ds = Math.Sqrt(dx * dx + dy * dy);
                if (ds >= dinterp)
                {
                    poly1[ipt] = polygon[i];
                    ++ipt;
                }


            }
            poly = new PointF[ipt];
            for (int i = 0; i < ipt; ++i) poly[i] = poly1[i];

        }

 
    
    }
}
